package com.mamingchao.basics.designpattern.proxy.dynamic_proxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 这个是jdk java.lang.reflect 的版本的proxy
 *
 *  System.getProperties().setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true"); 这个配置没生效？
 *  因为生成的$Proxy0 没看见
 *
 * Created by mamingchao on 2020/10/16.
 */
public class ProxyTester {

    public static void main(String[] args) {
        Tank tank = new Tank();
        System.getProperties().setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");

        Movable m = (Movable) Proxy.newProxyInstance(Tank.class.getClassLoader(), new Class[]{Movable.class},

//                new InvocationHandler() {
//            @Override
//            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//
//                Long startTime = System.currentTimeMillis();
//                System.out.println(method.getName());
//                method.invoke(tank,objects);
//                Long endTime = System.currentTimeMillis();
//                System.out.println("The move method has cost millis seconds--" + (endTime-startTime));
//                return null;
//            }
//        }
                new LogProxy(tank)
        );

        m.move();
    }
}

interface Movable{
    void move();
}

class Tank implements Movable {

    @Override
    public void move() {
        System.out.println("Tank is moving");

        try {
            TimeUnit.SECONDS.sleep(new Random(10).nextInt());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class LogProxy implements InvocationHandler {
    Movable m;

    public LogProxy(Movable m) {
        this.m = m;
    }
    private void before(){System.out.println("Start  logging....");}
    private void after(){System.out.println("End  logging....");}

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        m.move();
        after();
        return null;
    }
}

